package org.xlp.base.application;

import com.alibaba.druid.pool.DruidDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xlp.base.application.constant.ApplicationConst;
import org.xlp.base.application.constant.StartingParameterConst;
import org.xlp.base.application.constant.inner.InnerConstants;
import org.xlp.base.application.context.AppApplicationContext;
import org.xlp.base.application.dao.ApplicationBaseDaoHelper;
import org.xlp.base.application.sysout.ReportUtils;
import org.xlp.base.application.util.ApplicationUtils;
import org.xlp.base.application.util.PropertiesFileReaderUtils;
import org.xlp.base.application.util.SQLFileParseUtils;
import org.xlp.db.bridge.annotation.Mapper;
import org.xlp.db.bridge.defination.MapperAnnotationBeanDefinitionCreator;
import org.xlp.db.bridge.helper.DaoBridgeHelper;
import org.xlp.db.utils.XLPDBUtil;
import org.xlp.mvc.listener.BaseApplicationListener;
import org.xlp.mvc.register.BeanDefinitionCreatorRegister;
import org.xlp.scanner.annotation.Scanner;
import org.xlp.utils.XLPStringUtil;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import java.io.File;
import java.io.InputStream;
import java.util.Properties;

/**
 * Create by xlp on 2020/11/26
 * <p>
 * Tomcat 启动监听
 */
@Scanner
public class AppApplicationListener extends BaseApplicationListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(AppApplicationListener.class);

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext sc = sce.getServletContext();
        // 设置配置文件的根目录
        setConfigBaseDir(sc);

        String isReport = sc.getInitParameter(InnerConstants.CONTEXT_PARAM_KEY_IS_REPORT);
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("获配置信息isReport=" + isReport);
        }
        if (isReport != null && !"true".equals(isReport)) {
            ReportUtils.setIsReport(false);
        }

        //初始化数据库连接池
        initDataSource(sc);

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("数据初始化完成。");
        }

        //sql文件解析功能
        parseSqlFiles();

        // 创建bean上下文容器
        BeanDefinitionCreatorRegister.register(Mapper.class, new MapperAnnotationBeanDefinitionCreator());
        try {
            AppApplicationContext.create(this.getClass(), this.getClass().getClassLoader());
        } catch (Exception e) {
            if (LOGGER.isErrorEnabled()){
                LOGGER.error("创建bean上下文容器失败", e);
            }
            throw new RuntimeException(e);
        }

        //注册BaseDao实例
        DaoBridgeHelper.register(ApplicationBaseDaoHelper.getApplicationBaseDao());
    }

    /**
     * 设置配置文件的根目录
     * @param sc Servlet上下文
     */
    protected void setConfigBaseDir(ServletContext sc){
        String realPath = sc.getRealPath("/");
        ApplicationUtils.setConfigBaseDir(realPath + "WEB-INF" + File.separator + ApplicationConst.DEFAULT_CONFIG_BASE_DIR);
    }

    /**
     * 解析sql配置文件
     */
    protected void parseSqlFiles() {
        SQLFileParseUtils.parseSQLFile();
    }

    /**
     * 初始化数据库连接池
     * @param sc
     */
    protected void initDataSource(ServletContext sc) {
        if (LOGGER.isDebugEnabled()){
            LOGGER.debug("初始化数据库连接池开始。。。");
        }

        //获取druid数据库连接池配置
        Properties properties = new Properties();
        InputStream inputStream = AppApplicationListener.class.getClassLoader()
                .getResourceAsStream(InnerConstants.DEFAULT_DRUID_PROPERTIES_FILE_NAME);
        //加载类路径下的默认配置文件
        if (inputStream != null){
            properties = PropertiesFileReaderUtils.load(inputStream);
        }

        File druidFile = new File(ApplicationUtils.getConfigBaseDir(), InnerConstants.DEFAULT_DRUID_PROPERTIES_FILE_NAME);
        //加载配置文件夹的默认配置文件
        if (druidFile.isFile()){
            properties.putAll(PropertiesFileReaderUtils.loadFromAbsolutePath(druidFile.getAbsolutePath()));
        }
        //加载web.xml中的配置文件
        String druidConfigFile = sc.getInitParameter(InnerConstants.CONTEXT_PARAM_KEY_DRUID_PROPERTIES);
        if (!XLPStringUtil.isEmpty(druidConfigFile)){
            if (druidConfigFile.startsWith(InnerConstants.CLASS_PATH_PRE)){
                druidConfigFile = druidConfigFile.substring(InnerConstants.CLASS_PATH_PRE.length());
            }
            properties.putAll(PropertiesFileReaderUtils.loadFromRelativePath(druidConfigFile));
        }
        //加载启动参数配置的配置文件
        druidConfigFile = System.getProperty(StartingParameterConst.DRUID_CONFIG_FILE);
        if (!XLPStringUtil.isEmpty(druidConfigFile)){
            druidFile = new File(ApplicationUtils.getConfigBaseDir(), druidConfigFile);
            if (druidFile.isFile()){
                properties.putAll(PropertiesFileReaderUtils.loadFromAbsolutePath(druidFile.getAbsolutePath()));
            }
        }

        if (properties.isEmpty()){
            throw new RuntimeException("请先配置数据库相关的数据哦！！！");
        } else {
            //创建数据库连接池
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.configFromPropety(properties);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("druid数据库连接池配置信息：" + properties);
            }
            //初始化数据库连接池
            XLPDBUtil.initDataSource(druidDataSource);
        }

        if (LOGGER.isDebugEnabled()){
            LOGGER.debug("初始化数据库连接池完成。。。");
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //销毁数据库连接池
        try {
            ((DruidDataSource) XLPDBUtil.getDataSource()).close();
        } catch (Exception e) {
            if (LOGGER.isErrorEnabled()){
                LOGGER.error("数据库连接池关闭失败", e);
            }
        }
    }
}
